package gipf.trunk;

import java.util.ArrayList;

/**
 * @author eric
 *the game engine performs the moves, either by a player or by a bot
 *it also removes finished lines atomatically
 *it has the boardState int[], which describes the current configuration
 *of the board
 */
public class GameEngine {

	public static int[] playerList;
	public static int[] piecesAvailable = new int[2];

	public static State boardState;
	public int turn;
	private static action nextAction;
	private int playerInTurn;
	private boolean gameOver = false;
	private boolean[] human = new boolean[2];

	private ArrayList<int[]> boardStates = new ArrayList<int[]>();
	ArrayList<action> performedActions = new ArrayList<action>();
	private position placePiece;

	// public static int[] currentBoard = new;

	/**
	 * @param argP number of human players
	 * @param string not used yet, only standart version of the game.
	 */
	public GameEngine(int argP, String string) {

		switch (argP) {
		case 0:
			human[0] = false;
			human[1] = false;
			break;
		case 1:
			human[0] = true;
			human[1] = false;
			break;
		case 2:
			human[0] = true;
			human[1] = true;
			break;

		}
		boardState = new State();
		playerList = new int[2];
		playerList[0] = 1;
		playerList[1] = 2;

		piecesAvailable[0] = 15;
		piecesAvailable[1] = 15;

		// TODO Auto-generated constructor stub
	}

	/**
	 * @return all states that the board went trough, in means of int[]'s 
	 */
	public ArrayList<int[]> getStates() {
		return boardStates;
	}

	/**
	 * perform either the human or the bot action
	 */
	public void perform() {

		int[] pieces = new int[61];

		playerInTurn = playerList[turn % playerList.length];

		if (human[playerInTurn - 1]) {
			nextAction = BoardView.getAction();
			BoardView.resetAction();

			nextAction.setPlayer(playerInTurn);
			if (nextAction.getPlacePosition() != null) {
				placePiece = nextAction.getPlacePosition();
				boardState.placePiece(placePiece,
						playerInTurn, false);
				piecesAvailable[turn % playerList.length]--;
			}
				if (nextAction.getMovePosition() != null) {
					int direction = staticBoard.determineDirection(
							placePiece,
							nextAction.getMovePosition()); 
					boardState.movePiece(
							placePiece,
							direction);
					
					if (nextAction.getTakeIndex() == 0) {
						ArrayList<ArrayList<Integer>> finishedLines = staticBoard
								.finishedLines(boardState, direction);

						if (!finishedLines.isEmpty()) {
							for (int i = 0; i < finishedLines.size(); i++) {
								int p = removeLines(finishedLines, i);

							}
							pieces = boardState.getPieces().clone();
							boardStates.add(pieces);

						}
					}
				turn++;

				gameOver = gameOver();
			}

		} else {
			nextAction = new action(playerInTurn);
			nextAction.createRandomMove(boardState.getPieces());

			boardState.placePiece(nextAction.getPlacePosition(), playerInTurn,
					false);
			piecesAvailable[turn % playerList.length]--;

			boardState.movePiece(
					nextAction.getPlacePosition(),
					staticBoard.determineDirection(
							nextAction.getPlacePosition(),
							nextAction.getMovePosition()));

			pieces = boardState.getPieces().clone();
			boardStates.add(pieces);
			performedActions.add(nextAction);

			ArrayList<ArrayList<Integer>> finishedLines = staticBoard
					.finishedLines(
							boardState,
							staticBoard.determineDirection(
									nextAction.getPlacePosition(),
									nextAction.getMovePosition()));

			if (!finishedLines.isEmpty()) {
				for (int i = 0; i < finishedLines.size(); i++) {
					int p = removeLines(finishedLines, i);

				}
				pieces = boardState.getPieces().clone();
				boardStates.add(pieces);

			}

			turn++;

			gameOver = gameOver();
		}

	}

	/**
	 * @param finishedLines Arraylist of all finished lines
	 * @param index of the line (if there is only one finished line, this is 0)
	 * @return which player profited from removing that line
	 */
	private int removeLines(ArrayList<ArrayList<Integer>> finishedLines,
			int index) {
		int takenBy = 0;
		int p1 = 0;
		int p2 = 0;

		for (int i = 0; i < finishedLines.get(index).size(); i++) {
			if (boardState.getPieces()[finishedLines.get(index).get(i)] == 1) {
				p1++;
			} else if (boardState.getPieces()[finishedLines.get(index).get(i)] == 2) {
				p2++;
			}

		}

		if (p1 >= 4) {
			piecesAvailable[0] += p1;
			takenBy = 1;
		} else if (p2 >= 4) {
			piecesAvailable[1] += p2;
			takenBy = 2;
		}

		if (takenBy != 0) {
			for (int i = 0; i < finishedLines.get(index).size(); i++)
				boardState.getPieces()[finishedLines.get(index).get(i)] = 0;
			return takenBy;
		}

		return 0;

	}

	/**
	 * @return if the game is over
	 */
	public boolean gameOver() {
		if (piecesAvailable[0] == 0 || piecesAvailable[1] == 0)
			return true;
		return false;
	}

	/**
	 * @param tickInterval
	 * @throws InterruptedException
	 * 
	 * tick thing
	 */
	public void tick(long tickInterval) throws InterruptedException {
		while (!gameOver) {
			Thread.sleep(tickInterval);

			perform();
			BoardView.panel.repaint();

			// ArrayList<Piece> toBeAdded = (ArrayList<Piece>)
			// boardInstance.getSnapShot().clone();
			// createdBoards.add(toBeAdded);
		}
		;
	}
}

